package view;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.IntrospectionException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.rmi.RemoteException;

import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;

import rmi.Discussion;
import rmi.DiscussionInterface;
import rmi.Me;
import rmi.UserBuffer;
import controler.xmlReadWrite;

/**
 * @author REMY Timothée and CARTIER Arthur
 *
 */
public class menuBar extends JMenuBar {
	public class AddBlackList implements ActionListener {
		@SuppressWarnings("unused")
		@Override
		public void actionPerformed(final ActionEvent e) {
			String blacklist;
			blacklist = JOptionPane
					.showInputDialog(
							null,
							"Enter the user's nickname you want to add in your blacklist",
							"Nickname", JOptionPane.QUESTION_MESSAGE);
			if (blacklist != null && blacklist.length() == 0) {
				final JOptionPane infoPseudo = new JOptionPane();
				JOptionPane.showMessageDialog(null, "Nick has to be not null",
						"New Nickname", JOptionPane.INFORMATION_MESSAGE, null);
			} else if (blacklist != null && blacklist.length() > 0) {
				final JOptionPane infoPseudo = new JOptionPane();
				JOptionPane.showMessageDialog(null, blacklist
						+ " has been added to your blacklist.", "New Nickname",
						JOptionPane.INFORMATION_MESSAGE, null);
				me.getBlacklist().add(blacklist);
			}

		}

	}

	public class AddFriend implements ActionListener {
		@Override
		public void actionPerformed(final ActionEvent e) {
			final String labels[] = { "Pseudo", "IP", "Port" };
			String results[];

			final MultipleStringDialog msd = new MultipleStringDialog(
					mainWindow,
					"Nouveau contact",
					true,
					labels,
					"Entrez le pseudo, ainsi que si vous les connaissez, l'adresse Ip et le port de votre ami");

			msd.setVisible(true);

			results = msd.getResults();

			UserBuffer newFriend = null;

			if (results[0] != null && results[0].length() > 0
					&& results[1] != null && results[1].length() > 0
					&& results[2] != null && results[2].length() > 0) {
				newFriend = new UserBuffer(results[0], results[1],
						Integer.parseInt(results[2]));
			} else if (results[0] != null && results[0].length() > 0) {
				newFriend = new UserBuffer(results[0]);
			}

			// TODO ask again or abort and say it if pseudo is empty

			me.getFriends().put(results[0], newFriend);
			me.connectAllDisconnectedFriends();

			mainWindow.repaint();
		}
	}

	public class ChangeNickName implements ActionListener {
		@SuppressWarnings("unused")
		@Override
		public void actionPerformed(final ActionEvent arg0) {
			String mynickname;
			mynickname = JOptionPane.showInputDialog(mainWindow,
					"Enter your new nickname", "Nickname",
					JOptionPane.QUESTION_MESSAGE);
			if (mynickname != null && mynickname.length() == 0) {
				final JOptionPane infoPseudo = new JOptionPane();
				JOptionPane.showMessageDialog(null, "Nick has to be not null",
						"New Nickname", JOptionPane.INFORMATION_MESSAGE, null);
			} else if (mynickname != null && mynickname.length() > 0) {
				final JOptionPane infoPseudo = new JOptionPane();
				JOptionPane.showMessageDialog(null, "You are now known as\n"
						+ mynickname, "New Nickname",
						JOptionPane.INFORMATION_MESSAGE, null);
				me.setPseudo(mynickname);
			}
		}
	}

	public class DelBlackList implements ActionListener {

		@SuppressWarnings("unused")
		@Override
		public void actionPerformed(final ActionEvent arg0) {
			String blacklist;
			blacklist = JOptionPane
					.showInputDialog(
							null,
							"Enter the user's nickname you want to r from your blacklist",
							"Nickname", JOptionPane.QUESTION_MESSAGE);
			if (blacklist != null && blacklist.length() == 0) {
				final JOptionPane infoPseudo = new JOptionPane();
				JOptionPane.showMessageDialog(null, "Nick has to be not null",
						"New Nickname", JOptionPane.INFORMATION_MESSAGE, null);
			} else if (blacklist != null && blacklist.length() > 0
					&& !me.getBlacklist().contains(blacklist)) {
				final JOptionPane infoPseudo = new JOptionPane();
				JOptionPane.showMessageDialog(null, "Nobody called "
						+ blacklist + " is contained in your blacklist",
						"New Nickname", JOptionPane.INFORMATION_MESSAGE, null);

			} else if (blacklist != null && blacklist.length() > 0
					&& me.getBlacklist().contains(blacklist)) {
				final JOptionPane infoPseudo = new JOptionPane();
				JOptionPane.showMessageDialog(null, blacklist
						+ " has been removed from your blacklist.",
						"New Nickname", JOptionPane.INFORMATION_MESSAGE, null);
				me.getBlacklist().remove(blacklist);
			}

		}
	}

	public class ExitApp implements ActionListener {
		@Override
		public void actionPerformed(final ActionEvent ae) {

			for (final Discussion d : me.getCurrentDiscussions()) {
				for (final DiscussionInterface distantD : d
						.getListDiscussions()) {
					try {
						distantD.leave(me.getPseudo());
					} catch (final RemoteException e) {
						// We try once again (but just once)
						try {
							distantD.leave(me.getPseudo());
						} catch (final RemoteException e1) {
							// Too bad
						}
					}
				}
			}

			for (final UserBuffer u : me.getFriends().values()) {
				try {
					u.disconnect(me.getPseudo());
				} catch (final RemoteException e) {
					// We try once again
					try {
						u.disconnect(me.getPseudo());
					} catch (final RemoteException e1) {
						// Too bad
					}
				}
				try {
					u._setDistantUser(null);
				} catch (final RemoteException e) {
					// this error can't append when the parameter is null
				}
			}

			final JFileChooser jfc = new JFileChooser("~");
			int result;

			if (me.getSaveDiscussionsFolder() == null
					|| me.getSaveDiscussionsFolder().isEmpty()) {
				jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
				jfc.setDialogTitle("Select the backup folder for your discussions");
				result = jfc.showSaveDialog(mainWindow);

				if (result == JFileChooser.APPROVE_OPTION) {
					try {
						me.setSaveDiscussionsFolder(jfc.getSelectedFile()
								.getCanonicalPath().toString());
					} catch (final IOException e) {
						System.err
								.println("We can't get the canonical path of The selected saveMefile");
						e.printStackTrace();
					}

				}
			}

			if (me.getSaveDiscussionsFolder() != null
					&& !me.getSaveDiscussionsFolder().isEmpty()) {
				try {
					xmlReadWrite.saveDiscussions(me.getCurrentDiscussions(),
							me.getSaveDiscussionsFolder());
				} catch (final FileNotFoundException e) {
					System.err.println("the folder has not been found");
					e.printStackTrace();
				}
			}

			if (me.getSaveMeFile() == null || me.getSaveMeFile().isEmpty()) {
				jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
				jfc.setDialogTitle("Select the backup file");
				result = jfc.showSaveDialog(mainWindow);

				if (result == JFileChooser.APPROVE_OPTION) {
					try {
						me._setSaveMeFile(jfc.getSelectedFile()
								.getCanonicalPath().toString());
					} catch (final IOException e) {
						System.err
								.println("We can't get the canonical path of The selected saveMefile");
						e.printStackTrace();
					}
				}
			}

			if (me.getSaveMeFile() != null && !me.getSaveMeFile().isEmpty()) {
				try {
					xmlReadWrite.saveMe(me, me.getSaveMeFile());
				} catch (final FileNotFoundException e) {
					System.err.println("the file has not been found");
					e.printStackTrace();
				} catch (final IntrospectionException e) {
					// this error can't occur
					System.err.println("the me object can't be serialized");
					e.printStackTrace();
				}
			}

			System.exit(0);
		}
	}

	public class ModifyMyIP implements ActionListener {

		@Override
		public void actionPerformed(final ActionEvent e) {
			final String labels[] = { "IP", "Port" };
			String results[];

			final MultipleStringDialog msd = new MultipleStringDialog(
					mainWindow, "Change IP and Port", true, labels,
					"Entrez votre adresse Ip et un port libre");

			msd.setVisible(true);

			results = msd.getResults();

			me.setIp(results[0]);
			me.setPort(Integer.parseInt(results[1]));

			// TODO check errors

		}
	}

	public class OpenDiscuss implements ActionListener {
		@Override
		public void actionPerformed(final ActionEvent ae) {
			boolean isCanceled = false;

			int result = 0;

			Discussion oldDiscussion = null;

			while ((!isCanceled) && oldDiscussion == null) {

				final JFileChooser jfc = new JFileChooser("~");

				jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
				jfc.setDialogTitle("Select the discussion backup file");
				result = jfc.showOpenDialog(mainWindow);

				if (result == JFileChooser.APPROVE_OPTION) {
					try {
						oldDiscussion = xmlReadWrite.restoreOneDiscussion(jfc
								.getSelectedFile().getCanonicalPath()
								.toString());
						if (oldDiscussion != null) {
							final OneDiscussionTab odt = new OneDiscussionTab(
									oldDiscussion, me);
							odt.bottomPanel.setEnabled(false);
							odt.newMessageField.setEnabled(false);
							odt.sendButton.setEnabled(false);
							mainWindow.getContactsList().addOneDiscussion(
									"Archive", odt);
						}

					} catch (final FileNotFoundException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (final IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				} else {
					isCanceled = true;
				}
			}
		}

	}

	public class OpenListener implements ActionListener {
		@Override
		public void actionPerformed(final ActionEvent arg0) {

		}
	}

	public class PrintUserInfos implements ActionListener {
		@SuppressWarnings("unused")
		@Override
		public void actionPerformed(final ActionEvent arg0) {
			final String pseudo = "Pseudo: " + me.getPseudo();
			final String ip = "\nIP address: " + me.getIp();
			final String port = "\nPort: " + me.getPort();
			String config;
			String historique;
			if (me.getSaveMeFile() != null) {
				config = "\nConfig path: " + me.getSaveMeFile();
			} else {
				config = "\nConfig path: Not defined";
			}
			if (me.getSaveDiscussionsFolder() != null) {
				historique = "\nSaved discussion path: "
						+ me.getSaveDiscussionsFolder();
			} else {
				historique = "\nSaved discussion path: Not defined";
			}
			final JOptionPane infos = new JOptionPane();
			JOptionPane.showMessageDialog(null, pseudo + ip + port + config
					+ historique, "User infos",
					JOptionPane.INFORMATION_MESSAGE, null);
		}
	}

	public class SaveListener implements ActionListener {

		@Override
		public void actionPerformed(final ActionEvent arg0) {

			if (me.getSaveMeFile() == null || me.getSaveMeFile().isEmpty()) {
				final JFileChooser jfc = new JFileChooser("~");
				jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
				jfc.setDialogTitle("Select the backup file");
				final int result = jfc.showSaveDialog(mainWindow);

				if (result == JFileChooser.APPROVE_OPTION) {
					try {
						me._setSaveMeFile(jfc.getSelectedFile()
								.getCanonicalPath().toString());

					} catch (final FileNotFoundException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (final IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}

			if (me.getSaveMeFile() != null && !me.getSaveMeFile().isEmpty()) {
				try {
					xmlReadWrite.saveMe(me, me.getSaveMeFile());
				} catch (final FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (final IntrospectionException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	public class WhatVersion implements ActionListener {
		@SuppressWarnings("unused")
		@Override
		public void actionPerformed(final ActionEvent e) {
			final String dev = "Developped by \nArthur CARTIER & Timothée REMY\n";
			final String vers = "Version 1.00";
			final JOptionPane v = new JOptionPane();
			JOptionPane.showMessageDialog(null, dev + vers, "À propos",
					JOptionPane.INFORMATION_MESSAGE, null);
		}
	}

	/**
	 * 
	 */
	private static final long serialVersionUID = 3574221029361423616L;
	private final JMenu file;
	private final JMenuItem quit;
	private final JMenuItem save;
	private final JMenuItem ouvrir;
	private final JMenu user;
	private final JMenuItem userInfos;

	private final JMenuItem changePseudo;

	private final JMenuItem ipModify;

	private final JMenu action;

	private final JMenuItem addFriend;

	private final JMenuItem addBlackList;

	private final JMenuItem delBlackList;

	private final JMenuItem openDiscuss;

	private final JMenu help;

	private final JMenuItem version;

	private final MainWindow mainWindow;

	private final Me me;

	public menuBar(final Me me, final MainWindow mw) {
		super();
		this.me = me;
		mainWindow = mw;

		file = new JMenu("Fichier");
		ouvrir = new JMenuItem("Ouvrir");
		save = new JMenuItem("Save");
		quit = new JMenuItem("Quit");

		user = new JMenu("User");
		userInfos = new JMenuItem("User infos");
		changePseudo = new JMenuItem("Config User");
		ipModify = new JMenuItem("IP address");
		openDiscuss = new JMenuItem("Open old discussion");

		action = new JMenu("Action");
		addFriend = new JMenuItem("Add a friend");
		addBlackList = new JMenuItem("Add into blacklist");
		delBlackList = new JMenuItem("Remove from blacklist");

		help = new JMenu("Help");
		version = new JMenuItem("Version");

		changePseudo.addActionListener(new ChangeNickName());
		ipModify.addActionListener(new ModifyMyIP());
		userInfos.addActionListener(new PrintUserInfos());
		openDiscuss.addActionListener(new OpenDiscuss());
		addFriend.addActionListener(new AddFriend());
		addBlackList.addActionListener(new AddBlackList());
		delBlackList.addActionListener(new DelBlackList());

		ouvrir.addActionListener(new OpenListener());
		save.addActionListener(new SaveListener());
		quit.addActionListener(new ExitApp());
		version.addActionListener(new WhatVersion());
		// action.add(changePseudo);
		user.add(userInfos);
		user.add(ipModify);
		user.add(openDiscuss);
		action.add(addFriend);
		action.add(addBlackList);
		action.add(delBlackList);

		file.add(ouvrir);
		file.add(save);
		file.add(quit);
		help.add(version);

		this.add(file);
		this.add(user);
		this.add(action);
		this.add(help);
		setVisible(true);
	}

}
